3.2 Something more about JavaScript I

  1. Motivations
    • We would like to build a JavaScript library to support jQuery-like features, so that other programmers can use your library.
    • What do you have to do? Just functions? Or classes?
    • We need more knowledge and skills of JavaScript.
    • We will also use JavaScript as a server-side scripting language.

  2. Learning outcomes
    • How to use 'var' and 'let' in different ways
    • How to create/use objects
    • How to dynamically update objects and arrays
    • How to use closures
    • How to use module patterns
    • How to use callback functions with this and closures

  3. Programming environments with JavaScript
    • JavaScript is a general purpose scriting programming language that includes common structured and modular programming syntaxes. It can be used in the web browser environment and in any computer systems.
    • The web browser environment with JavaScript:
      • JS code is executed on a web browser.
      • JS code is used to access HTML elements, and for event-driven programming and AJAX communication and ....
      • Two objects, window and document, that represent a client-side web application and all HTML elements are visible in JS code.
    • General programming environment with JavaScript:
      • Node.js is a name of JavaScript programming environment that includes a package of JavaScript libraries.
      • It can be used on the sever side.
      • A question, can two the objects, window and document, be used?

  4. Function/Object in JavaScript - You need to have better understanding here.
    • JavaScript Tutorial
      • How 'let' and 'var' are different?
        'let' and 'const' variables ared used with the block scope rule, and 'var' variables are used with the function scope rule.
        With 'var' a variable can be redeclared even when the variable already exists. E.g., var p = 10; ... var p = 15; alert(p);
        Another difference is, on the client side, global 'var' variables will be created in the window object as a property.
        Let's not use 'var' variables if possible.
        Trial 0.0.1


      • Read all in JavaScript Functions.
        • For what do you use functions?
        • How are 'toCelsius()' and 'toCelsius' different in the 4th example?
        • Function in the 4th example is a value? This is very interesting.
        • Can you assign a function to a variable? If so, how to use the function variable?
      • Read all in JavaScript Objects.
        • What do real life objects contain?
        • What do JavaScript objects contain?
        • How to define an object?
        • What are object properties?
        • What is a method?
        • Give two different styles to access object properties.
          obj.property_name or obj['property_name']
        • Give two different styles to access object methods.
          obj.method_name(...) or obj['method_name'](...)
        • How to add a new property into an object at run time?
          let property_name = ...; let property_value = ...; obj[property_name] = property_value;
        • How to add a new method into an object at run time?
          let method_name = ...; let method_code = ...; obj[method_name] = method_code; obj[method_name](...);
        • Are functions objects?
      • Read all in JavaScript Scope.
        • What is the role of the var keyword and when to use it (or omit it)?
          • In the global scope, there's no difference.
          • In a local scope, 'var' will create a local variable, and no 'var' will look up the scope chain until it finds the variable or hits the global scope (at which point it will create it).
          • Here is an example.
            // These are both globals.
            var foo = 1;  // This variable with 'var' will be created in the 'window' object as a property. 
                          // If the property exists, it will be overwritten. Need to be careful.
            bar = 2;      // Same as above
            
            function test_scope() {
                var foo = 1; // Local
                bar = 3;     // Global
            
                // Execute an anonymous function. Isn't it interesting?
                (function() {
                    var wibble = 1; // Local
                    foo = 2; // Inherits from the scope above (creating a closure)
                    moo = 3; // Global
                })();
            }
            
            test_scope();
            
        • Study closely the code of the last example.
        • What object is used to keep the global variables created with 'var' or without 'var' and 'let'? What if a property of the object is overwritten?
          window
      • Read all in JavaScript Arrays.
        • How to create an array?
        • List the two different styles of array creation.
        • Can you put different objects to one array?
        • How are arrays different from objects?
        • List some built-in array properties and methods.
        • How to add a new element to an array?
          data[anyindex] = ...;
        • Are arrays with named indexes supported? They are called associative arrays.
        • Here is one thing that you really need to be careful. If you use a named index, when accessing an array, JavaScript will redefined the array to a standard object, and all array methods and properties will produce undefined or incorrect results. Study closely the 11th example.
        • But try the 11th example after you add person[2] = 'Dave';. What do you see?
        • What is the difference between arrays and objects?
        • The reason not to use 'new Array(...)'. Study closely the 13th example.
        • How do you know if a variable is an array or object?
          Array.isArray(data)
        • Are arrays objects?

    • JavaScript Objects
      • Read all in JavaScript Objects.
        • Almost everything is an ???
        • All values, except primitive values, are ???
        • List 6 primitive values.
        • is an object method an object property? If so, what is contained?
        • What are the three different ways to create new objects?
        • How to put a new property to an object?
        • What keyword is used to define an object constructor function?
        • What is the benefit to use an object constructor function?
        • What is the value of 'this'?
        • How to create a new function object?
        • What does 'JavaScript objects are mutable.' mean? Study closely the last example.
      • Read all in JavaScript Object Properties.
        • List the two types of accessing object properties.
        • What kind of loop is used for objects?
          for...in and for...of
        • Can you add a new property to an object?
        • Can you delete an object property?
          delete person.age;
        • [
          • List the 5 property attributes.
          • Here is an example how to define and read property attributes. This is from JavaScript: Property Attributes: Writable, Enumerable, Configurable.
            var x = {};
            Object.defineProperty(x, "p", { value : 3, writable: true, enumerable: false, configurable: true});
            Object.defineProperty(x, "p", { writable: false} );
            alert(Object.getOwnPropertyDescriptor(x, "p").writable);  // .getOwnPropertyDescriptor() returns {vale:..., writable:..., enumerable:..., configurable:...}. 
            
          • Can you add a read-only property?
          • What is a prototype?
          ]
      • Read all in JavaScript Object Methods.
        • Is a method a property?
        • Study the last example carefully.
        • How to add a new method into an object? How to add a new method into an object constructor? You can find all the answers from the next topic.
      • Read all in JavaScript Objects Constructors.
      • [Read all in JavaScript Objects Prototypes.]
        • All objects inherit the properties and methods from their ???.
        • Object.prototype
        • All objects inherit the Object.???.
        • How can you create an object prototype?
        • How to create new objects from the same prototype?
        • How to add a new property/method to an existing object?
        • How to add a new property/method to an object prototype?
        • Can you use prototype property to add a new property/method to an object prototype?
        • What if you put a return statement in an object constructor function?

    • JavaScript Functions
      • Read all in JavaScript Function Definitions.
        • What is an anonymous function?
        • What is 'function hosting'? Variables too?
        • What is 'self-invoking functions'? Study closely the syntax in self-invoking.
        • Functions are objects. Hence they have both properties and methods.
          • Study the second last example.
          • arguments.length - Doesn't 'arguments' look like an array?
          • .toString()
        • Arrow functions: We will discusss about it later.
      • Read all in JavaScript Function Parameters.
        • What value is stored in missing arguments?
        • Does a function definition have to include all the parameters?
        • Can you pass different number of arguments to the same function? If so, how can you handle all the arguments?
        • Are objects passed to a function by value or by reference? How are they different?
      • Read all in JavaScript Function Invocation.
        • What value of 'this' is?
        • When a function is called without a specific owner object, to which object do functions belong? Study closely the 2nd example.
        • Functions can be
          • Functions/methods like in other most programming languages
          • Prototypes (or also called object constructors). In this case, we'd better say the function is invoked, not called.
          • Objects - List the two predefined methods.
        • How can you know which function is a regular function, method, prototype, or object?
      • Read all in JavaScript Closures.
        • All the properties defined in a prototype are public.
        • How can you define private variables?
        • How can you define static variables in a function?
        • Study very closely the last example.
        • What is a closure? A closure is a function having access to the parent scope, even after the parent function has closed, or a closure is defined as the set of local variables in a function that are kept alive after the function has returned.
        • How does a closure create private variables and static variables?

  5. Some other more advanced and very important topics
    • 3 ways to create a JavaScript object
      • Idea 1. Using an object constructor
        function Apple (type) {  // This is similar to the definition of a class in Java.
                                 // The keyword is function, not class.
                                 // A function is a constructor that is instantiated later.
            this.type = type;  // this.type: global; type: local
            this.color = "red";
            this.getInfo = function() {
                return this.color + ' ' + this.type + ' apple';
            };
        };
        var apple = new Apple('macintosh');  // keyword 'new' to create an object
        apple.color = "reddish";
        alert(apple.getInfo());
        //-----------------------------------------------------------
        function Car (type, color) {
            this.type = type;
            this.color = color;
        };
        var passat = new Car('passenger', 'black');
        Car.prototype.size = 'small';
        Car.prototype.getInfo = function() {  // Car.prototype
            return this.color + ' ' + this.type + ' car';
        };
        var golf = new Car('passenger', 'silver');
        alert(golf.getInfo());
        alert(passat.getInfo());  // ???
        
      • Singleton using a function (Actually using anonymous object constructor)
        var apple = new function() {
            this.type = "macintosh";
            this.getInfo = function () {
                return this.color + ' ' + this.type + ' apple';
            };
        }
        apple.color = "reddish";
        alert(apple.getInfo());
        
      • Trial 0.1: Let's write the library, TRUEcho1, that supports a simple echo service. It has a property and three methods.


      • Idea 2. Using object literals
        var o = {};  // or var o = new Object();
        // for arrays
        var a = [];  // or var a = new Array();
        //-----------------------------------------------------------
        var apple = {  // In this case you cannot create another instance of the class later.
            type: "macintosh",
            color: "red",
            getInfo: function () {
                return this.color + ' ' + this.type + ' apple';
            }
        }
        apple.color = "reddish";
        alert(apple.getInfo());
        //-----------------------------------------------------------
        var apple = {};
        apple.type = 'Gala';  // Not apple.prototype.type. Why?
        apple.color = 'Red';
        apple.getInfo = function () {
            return this.color + ' ' + this.type + ' apple';
        };
        alert(apple.getInfo());
        
      • Trial 0.5: Let's write the code that reads input and creates a property within objects $trujs and $trujs._expressions with its value. The property name is given with a user-defined attribute 'trujs-model'.


      • Idea 3. Using a function that returns an object
        For example,
        function fruit(type) {
            if (type == "GoldenDelicious")
                return {
                    type: "GoldenDelicious",
                    color: "yellow",
                    getInfo: function () {
                        return this.color + ' ' + this.type + ' apple';
                    }
                }
            else if (type == "PinkLady")
                return {
                    type: "PinkLady",
                    color: "pink",
                    getInfo: function () {
                        return this.color + ' ' + this.type + ' apple';
                    }
                }
            else    
                return {
                    type: "Unknown";
                }
        }
        var apple = fruit("GoldenDelicious");
        alert(apple.getInfo);
        
      • Trial 0.6: Let's write the $trujq function that has a paramter of CSS selector and returns an object. The returned object needs to have the method click() that responses to the click event on the HTML elements that are selected with the passed CSS selector.



    • Closures and module patterns
      • Do you understand scope rules?
        • Read 'Global variables', 'Variable Life', 'A Counter Dilema' in JavaScript Closures
          • How can you keep static variables in a function?
          • What is JavaScript closure?
          • Can a function return a function?
          • How can you use private variables?
      • When an object is created with 'new' keyword, are all the properties accessible through the object variable?
        • Yes.
        • Review the examples in the above section.
      • How to provide an object with private/public properties and methods?
        • Read 'JavaScript Closures' in JavaScript Closures again.
          • What is a closure?
          • In the closure example code in the above link, what value does add have?
        • Module pattern
          For example,
          const person = (function(n, a) {  // What value does person have? function() { ... or the returned function?
                                          // What is (function() { ... })()? Function invocation?
              let name = n;
              let age = a;
              return {  // What kind of data is returned?
                  first_name: name,
                  get_name: function() { return name; },  // NOT this.name
                  set_name: function(new_name) { name = new_name; },
                  get_age: function() { return age; },  // NOT this.age
                  set_age: function(new_age) { age = new_age; }
              };
          })('Tim', 22);
          alert(person.age);  // undefined; why???
          person.name = 'Gildong';  // This name is not the private variable name. Why???
          alert(person.first_name);  // 'Tim'
          person.first_name = 'Gildong';  // This first_name is the public variable first_name.
          alert(person.first_name);  // 'Gildong'; It does not change the private variable.
          alert(person.get_name());  // 'Tim'
          alert(person.get_age());
          person.set_age(24);
          alert(person.get_age());
          
        • There are many good tutorial web sites for module patterns.
        • We can hide public variables with a module pattern.
      • Trial 1: Let's write the Student function using the above Module pattern. The object returned from Student needs to keep private name and id. The object has setName(), getName(), setId(), and getId() methods to access them.


      • Trial 1.1: Let's write the $trujq function that has a parameter of CSS selector and returns an object. The returned object needs to have the method click() that responses to the click event on the selected HTML elements with the passed CSS selector. Note that the click() method has a parameter of function which will be invoked in a click event listener.


      • Trial 1.2: Let's write the $trujq function that has a parameter of CSS selector and returns an object. The returned object needs to have the method each() that goes through each selected HTML element. Note that the each() method has a parameter of function which will be invoked in each().



    • Callback functions
      • When are callback functions used?
        When a task, such as communication and file i/o, takes some time. Usually an event is used to indicate the completion of such task.
      • Trial 1.5: Let's write the function that reads n numbers, adds them and returns the result using a callback function.



    • The this keyword and functions, especially with callback functions
      • There are serveral things that we need to be careful with this.
      • Let's study the next example very carefully. What will be printed?
        <script>
        function printType(msg, x) {
            if (x == window) alert(msg + ": " + 'window');
            else if (x == document) alert(msg + ": " + 'document');
            else if (x instanceof HTMLElement) alert(msg + ": " + 'HTMLElement ' + x.id);
            else alert(msg + ": " + 'something else');
        }
        
        function foo() {
            printType("foo-this", this);  // what is this?
        }
        
        function goo(obj, callback) {
            printType("goo-this", this);  // what is this?
            foo();
            printType("goo-obj", obj);  // what is obj?
            callback();  // check 'this' in callback() carefully.
            
            // a very important trick; There is another way and we will see it later.
            obj.__TRUjQ__callback = callback;
            obj.__TRUjQ__callback();  // check 'this' in callback() carefully.
        }
        
        $('#tr1-button').click(function() {
            printType("button-click-this", this);  // what is this?
            
            let this_button = this;
            
            goo(this, function() {
                printType("goo-callback-this", this);  // what is this?
                printType("goo-callback-this_button", this_button);
            });
        });
        
        foo();
        </script>
        
        <p id='tr1-p'>Interesting!</p>
        <button id='tr1-button'>Click me!</button>
        
      • Very confusing. For better understanding,
        event listener for the click over the button:  // It is defined on the button HTMLElement object.
            alert() with this;
            goo(this, callback):  // goo is defined in ???.
                alert() with this;
                foo():  // foo is defined in ???.
                    alert() with this;
                alert() with the passed argument;
                callback():  // Where is it defined?
                    alert() with this;
                    alert() with this_button;
                obj.__TRUjQ__callback():
                    alert() with this;
                    alert() with this_button;
        
      • Trial 2: Let's try the above example, with the followings.


        The above example will print window, button, window, window, button, window, button, button, button.
      • Let's study another example very carefully to see how var and let work differently. What will be printed?
        <script>
        function foo(lists) {
            let fts = [];
            for (let i = 0; i < lists.length; i++) {
                var p = lists[i];  // what if 'let' is used instead of 'var'?
                fts[i] = function() {
                    alert(p);  // p cannot be destroyed at the end of each for-iteration.
                               // what if 'lists[i]' is used instead of 'p'?
                };
            }
            return fts;  // array of functions
        }
        function goo() {
            let lists = [1, 2, 3];
            let fts = foo(lists);
            for (let i = 0; i < fts.length; i++)
                fts[i]();  // What will be printed? 1, 2, and 3?
        }
        $('#tr2-button').click(function() { goo(); });
        </script>
        <button id='tr2-button'>Click me to test the above code!</button>
        
      • Trial 3: Let's try the above example. Try the code again with let p = lists[i];.


        The above example will print 3, 3, and 3 with var p, but 1, 2, and 3 with let p. When this function is called, p is evaluated and it will be 3, 3, and 3.